<template>
  <el-dialog :title="title" :visible.sync="dialogVisible" width="40%">
    <div class="data-form-wrap">
      <el-form ref="dataForm" class="dataForm" :model="forms" :rules="rules" label-width="120px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model.trim="forms.roleName" placeholder="请输入角色名称" />
        </el-form-item>
        <el-form-item label="角色key" prop="roleKey">
          <el-input v-model.trim="forms.roleKey" placeholder="请输入角色key" />
        </el-form-item>
        <el-form-item label="资源权限" prop="resources">
          <!-- accordion -->
          <el-tree
            class="el-tree tree-border"
            :data="menuOptions"
            show-checkbox
            ref="menu"
            :default-checked-keys="defaultCheckedKeys"
            @check-change="checkChange"
            @check="treeCheck"
            node-key="id"
            :check-strictly="false"
            empty-text="加载中，请稍候"
            :props="defaultProps"
          ></el-tree>
        </el-form-item>
      </el-form>
    </div>
    <span slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="submitHandle">确 定</el-button>
    </span>
  </el-dialog>
</template>
<script>
import { getList as menuList } from '@/api/resourceManage'
import { addOrUpdRole, getRoleDetail } from '@/api/roleManage'
export default {
  name: 'Edit',
  data () {
    return {
      childNodeIds: [],
      menuOptions: [],
      title: '',
      dialogVisible: false,
      forms: {},
      defaultProps: {
        children: 'subRes',
        label: 'resName'
      },
      defaultCheckedKeys: [],
      rules: {
        roleName: [
          { required: true, message: '角色名称不能为空', trigger: 'blur' },
          { max: 20, message: '不能超过20个字符', trigger: 'blur' }
        ],
        roleKey: [
          { required: true, message: '角色key不能为空', trigger: 'blur' },
          { max: 20, message: '不能超过20个字符', trigger: 'blur' },
          {
            pattern: /^[A-Za-z]+$/,
            message: '只能输入纯字母',
            trigger: 'blur'
          }
        ],
        resources: [{ required: true, message: '资源权限不能为空', trigger: 'blur' }]
      }
    }
  },
  methods: {
    // 所有菜单节点数据
    getMenuAllCheckedKeys () {
      // 目前被选中的菜单节点
      const checkedKeys = this.$refs.menu.getCheckedKeys()
      // 半选中的菜单节点
      // const halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys()
      // checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
      return checkedKeys
    },
    treeCheck (data, node) {
      // const isChecked = this.$refs.menu.getNode(data)
      // console.log(data, data.resType, data.parentId, isChecked, 'node+++++')
      if (data.resType === 3) {
        this.findNodesByIdAndQuery(this.menuOptions, data)
      }
    },
    findNodesByIdAndQuery (array, data) {
      for (let i = 0; i < array.length; i++) {
        const element = array[i]
        if (element.id === data.parentId) {
          const findObj = element.subRes.find((v) => v.resName === '查询')
          if (findObj.id === data.id) {
            this.$refs.menu.setChecked(findObj.id, this.$refs.menu.getNode(data).checked)
            if (!this.$refs.menu.getNode(data).checked) {
              this.$refs.menu.setChecked(findObj.id, this.$refs.menu.getNode(data).checked)
              const filterArr = element.subRes.filter((v) => v.resName !== '查询')
              filterArr.forEach((v) => {
                this.$refs.menu.setChecked(v.id, false)
              })
            }
          } else {
            if (!this.$refs.menu.getCheckedKeys().includes(findObj.id)) {
              this.$refs.menu.setChecked(findObj.id, true)
            }
          }
        }
        if (element.subRes && element.subRes.length > 0) {
          this.findNodesByIdAndQuery(element.subRes, data)
        }
      }
    },
    checkChange () {
      // 使用 filter 方法和 includes 方法获取相同的 ID
      const commonIds = this.getMenuAllCheckedKeys().filter((id) => this.childNodeIds.includes(id))
      this.forms.resources = commonIds.map((v) => {
        return {
          resourceId: v
        }
      })
      this.$nextTick(() => {
        if (this.forms.resources.length > 0) {
          this.$refs.dataForm.clearValidate('resources')
        } else {
          this.$refs.dataForm.validateField('resources')
        }
      })
    },
    async open (str, row) {
      this.defaultCheckedKeys = []
      this.getMenuList()
      this.dialogVisible = true

      if (str !== 'update') {
        this.title = '新增角色'
        this.forms = {
          id: undefined,
          roleName: '',
          roleKey: '',
          resources: []
        }
      } else {
        this.title = '修改角色'
        const res = await getRoleDetail({ id: row.id })
        this.forms = res.data
        this.defaultCheckedKeys = res.data.resources.map((v) => v.resourceId)
      }
      this.$nextTick(() => {
        this.$refs.dataForm.clearValidate('resources')
      })
    },
    async getMenuList () {
      const res = await menuList({ keyword: '' })
      this.menuOptions = res.data
      this.childNodeIds = this.getChildNodeIds({ subRes: this.menuOptions })
    },
    // 递归函数遍历树形结构并获取最子节点的 ID
    getChildNodeIds (tree) {
      let ids = []
      if (tree.subRes && tree.subRes.length > 0) {
        // 遍历子节点
        tree.subRes.forEach((child) => {
          // 递归调用当前函数去遍历子节点的子节点
          const childIds = this.getChildNodeIds(child)
          // 将子节点的 ID 合并到当前节点的 ID 数组中
          ids = ids.concat(childIds)
        })
      } else {
        // 当前节点没有子节点，将当前节点的 ID 添加到结果中
        ids.push(tree.id)
      }
      return ids
    },
    async submitHandle () {
      this.$refs.dataForm.validate(async (valid) => {
        if (valid) {
          const res = await addOrUpdRole(this.forms)
          if (res.code === 'success') {
            this.$message.success('操作成功')
            this.dialogVisible = false
            this.$emit('getTableList')
            this.$refs.dataForm.resetFields()
          } else {
            this.$message.error(res.msg)
          }
        }
      })
    },
    normalizer (node) {
      if (!node.subRes) {
        delete node.subRes
      }
      return {
        id: node.id,
        label: node.resName,
        children: node.subRes
      }
    }
  }
}
</script>
<style scoped lang="scss">
.tree-border {
  margin-top: 5px;
  border: 1px solid #e5e6e7;
  background: #fff none;
  border-radius: 4px;
  height: 300px;
  overflow-y: auto;
}
</style>
